package com.knife.news.stat;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Time;
import java.util.StringTokenizer;

import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;

public class StatHandle {
    /**
     * 往数据库插入新的访问信息
     * @param ip String 用户IP地址
     * @param oper String
     * @param browser String
     * @throws Exception
     */
    public static void insert(String ip, String os, String browser,String url) throws
        Exception {
        Connection cnn = null;
        PreparedStatement ps = null;
        try {
            cnn = DBHandle.getConn(); //获取连接句柄
            ps = cnn.prepareStatement( //创建语句句柄
                "insert into k_history(k_ip,k_os,k_browser,k_url,k_accessdate,k_accesstime) values(?,?,?,?,?,?)");
            //填充参数
            ps.setString(1, ip);
            ps.setString(2, os.toUpperCase()); //存大写
            ps.setString(3, browser.toUpperCase());
            ps.setString(4, url);
            ps.setDate(5, new java.sql.Date(System.currentTimeMillis()));
            ps.setTime(6, new Time(System.currentTimeMillis()));
            ps.executeUpdate(); //执行语句
        }
        catch (Exception es) {
            throw es;
        }
        finally {
            DBHandle.closeResource(ps, null, cnn); //释放语句句柄和连接句柄
        }
    }

    /**
     * 往数据库插入新的访问信息
     * @param os String 操作系统
     * @param browser String 浏览器
     */
    public static void insert(String os, String browser,String url) throws
        Exception {
        Connection cnn = null;
        PreparedStatement ps = null;
        try {
            cnn = DBHandle.getConn();
            //获取连接句柄
            ps = cnn.prepareStatement(
                "insert into k_history(k_os, k_browser,k_url, k_accessdate, k_accesstime) values(?,?,?,?,?)");
            //创建语句句柄
            ps.setString(1, os.toUpperCase());
            //填充语句参数，将操作系统名称保存为大写
            ps.setString(2, browser.toUpperCase());
            //将浏览器名称保存为大写
            ps.setString(3, url);
            ps.setDate(4, new java.sql.Date(System.currentTimeMillis()));
            //访问日期为当天
            ps.setTime(5, new Time(System.currentTimeMillis()));
            //访问时间为当时
            ps.executeUpdate();
            //执行语句，往history表中插入一条记录
        }
        catch (Exception es) {
            throw es;
            //直接将异常抛出，由外部程序处理
        }
        finally {
            DBHandle.closeResource(ps, null, cnn);
            //释放语句句柄和连接句柄
        }
    }

    /**
     * 获取当月在内，前几月的访问数据，并保存到数据集（JFreeChart要用到）中
     * @param count int 要统计多少天的数据
     * @return DefaultCategoryDataset 返回数据集，里面包含前count月每月的访问次数
     */
    public static DefaultCategoryDataset getMonthStat(int count) throws
        Exception {
        Connection cnn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        DefaultCategoryDataset chart = new DefaultCategoryDataset();
        //数据集，用于保存前count月每月的访问次数
        try {
            cnn = DBHandle.getConn(); //获取连接句柄
            java.util.Date date = new java.util.Date();
            //创建日期对象，默认为当前日期
            for (int i = 0; i < count; i++) {
                //循环count次，依次获取给定月的访问次数并保存在数据集中
                String start = THandle.getStartDateofNMonth(date, count - i - 1);
                //获取前面第(count - i - 1)月的第一天的字符串表示
                //比如2006年3月份的第一天表示为为“2006-3-1”
                String end = THandle.getEndDateofNMonth(date, count - i - 1);
                //获取前面第(count - i - 1)月的最后一天的字符串表示
                //比如2006年3月份的最后一天表示为为“2006-3-31”
                String sql = "select count(*) from k_history";
                sql += " where k_accessdate>='" + start +
                    "' and k_accessdate<='" + end + "'";
                //获取前面第(count - i - 1)月的访问次数的SQL语句
                System.out.println(sql);
                //将SQL语句打印在日志信息中
                ps = cnn.prepareStatement(sql);
                //使用SQL字符串创建语句句柄
                rs = ps.executeQuery();
                //执行语句获取结果集
                rs.next();
                //游标指向结果集中第一条记录
                chart.addValue(rs.getInt(1), "访问量",
                               THandle.getNMonth(date, count - i - 1));
                //将前面第(count - i - 1)月的访问次数保存到数据集中
                DBHandle.closeResource(ps, rs, null);
                //释放在本次循环中的结果集和语句句柄
            }
        }
        catch (Exception es) {
            throw es;
            //直接将异常抛出，由外部程序处理
        }
        finally {
            DBHandle.closeResource(ps, rs, cnn);
            //释放连接句柄以及其他未释放的资源
        }
        return chart;
        //返回数据集
    }

    /**
     * 获取当天在内，前几天的访问数据，并保存到数据集（JFreeChart要用到）中
     * @param count int 要统计多少天的数据
     * @return XYDataset 返回数据集，里面包含前count天每天的访问次数
     */
    public static XYDataset getDayStat(int count) throws
        Exception {
        Connection cnn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        TimeSeriesCollection chart = new TimeSeriesCollection();
        //时间序列对象集合，里面可以存放多个TimeSeries对象，
        //TimeSeriesCollection实现了XYDataset接口
        TimeSeries timeseries = new TimeSeries("日访问", Day.class);
        //时间序列对象，第一个参数表示时间序列的名字，第二个参数是时间类型，这里为天
        //该对象用于保存前count天每天的访问次数
        try {
            cnn = DBHandle.getConn();
            //获取连接句柄
            java.util.Date date = new java.util.Date();
            //创建日期对象，默认为当前日期
            for (int i = 0; i < count; i++) {
                //循环count次，依次获取给定日期的访问次数并保存在数据集中
                String str = THandle.getLastDate(date, count - i - 1);
                //获取前面第(count - i - 1)天的日期的字符串表示
                String sql = "select count(*) from k_history where k_accessdate='" +
                    str + "'";
                //获取前面第(count - i - 1)天的访问次数的SQL语句
                System.out.println(sql);
                //将SQL语句打印在日志信息中
                ps = cnn.prepareStatement(sql);
                //使用SQL字符串创建语句句柄
                rs = ps.executeQuery();
                //执行语句获取结果集
                rs.next();
                //游标指向结果集中第一条记录
                StringTokenizer st = new StringTokenizer(str, "-");
                //从日期字符串str中，获取年、月、日
                int year = Integer.parseInt(st.nextToken());
                int month = Integer.parseInt(st.nextToken());
                int day = Integer.parseInt(st.nextToken());
                timeseries.add(new Day(day, month, year), rs.getInt(1));
                //将前面第(count - i - 1)天的访问次数保存到时间序列对象中
                DBHandle.closeResource(ps, rs, null);
                //释放在本次循环中的结果集和语句句柄
            }
        }
        catch (Exception es) {
            throw es;
            //直接将异常抛出，由外部程序处理
        }
        finally {
            DBHandle.closeResource(ps, rs, cnn);
            //释放连接句柄以及其他未释放的资源
        }
        chart.addSeries(timeseries);
        //将时间序列对象保存到时间序列对象集合中
        return chart;
        //返回数据集
    }

    /**
     * 将某一天各个时段的访问数据取出来并保存到数据集中
     * @param data DefaultCategoryDataset 数据集
     * @param date String 以字符串表示的日期
     * @param count int 每一天分成多少个时段
     * @throws Exception
     */
    public static void setHourStat(DefaultCategoryDataset data, String date,
                                   int count) throws
        Exception {
        Connection cnn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            cnn = DBHandle.getConn(); //获取连接句柄
            int length = 24 / count;
            //每个时段的长度，比如count = 4,那么每个时段长度为6
            for (int i = 0; i < count; i++) {
                //循环count次，依次获取每个时段的访问次数
                String start = i * length + ":00:00";
                //第i个时段的开始时间
                String end = ( (i + 1) * length - 1) + ":59:59";
                //第i个时段的结束时间
                String sql = "select count(*) from k_history";
                sql += " where k_accesstime>='" + start +
                    "' and k_accesstime<='" + end + "'";
                sql += " and k_accessdate='" + date + "'";
                //获取某一个时段访问量的SQL语句
                System.out.println(sql);
                //将SQL语句打印在日志信息中
                ps = cnn.prepareStatement(sql);
                //使用SQL字符串创建语句句柄
                rs = ps.executeQuery();
                //执行语句获取结果集
                rs.next();
                //游标指向结果集中第一条记录
                data.addValue(rs.getInt(1),
                              i * length + "-" + (i + 1) * length, date);
                //将三元组（访问次数，时段，访问日期）保存到数据集中
                DBHandle.closeResource(ps, rs, null);
                //释放在本次循环中的结果集和语句句柄
            }
        }
        catch (Exception es) {
            throw es;
            //直接将异常抛出，由外部程序处理
        }
        finally {
            DBHandle.closeResource(ps, rs, cnn);
            //释放连接句柄以及其他未释放的资源
        }
    }

    /**
     * 获取当天在内，前几天的各个时段的访问数据，并保存到数据集（JFreeChart要用到）中
     * @param dayCount int 要统计多少天的数据
     * @param count int 要统计多少个时段的数据
     * @return DefaultCategoryDataset 返回数据集，里面包含前count天每天的访问次数
     */
    public static DefaultCategoryDataset getHourStat(int dayCount, int count) throws
        Exception {
        DefaultCategoryDataset data = new DefaultCategoryDataset();
        //数据集，用于保存每天各个时段的访问数据
        try {
            java.util.Date date = new java.util.Date();
            //创建日期对象，默认为当前日期
            for (int i = 0; i < dayCount; i++) {
                //循环dayCount次，获取每天各个时段的访问数据
                String str = THandle.getLastDate(date, dayCount - i - 1);
                //获取前面第(count - i - 1)天的日期的字符串表示
                setHourStat(data, str, count);
                //将某一天各个时段的访问数据取出来并保存到数据集中
            }
        }
        catch (Exception es) {
            throw es;
        }
        return data;
        //返回数据集
    }
    /**
     * 获取OS类型统计,并保存到数据集（JFreeChart要用到）中
     * @throws Exception
     * @return DefaultPieDataset
     */
    public static DefaultPieDataset getosStat() throws
        Exception {
        Connection cnn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        DefaultPieDataset data = new DefaultPieDataset();
        //数据集，用于保存操作系统类型统计数据
        try {
            cnn = DBHandle.getConn();
            //获取连接句柄
            String sql = "select distinct k_os from k_history";
            //从历史记录表中获取操作系统类型
            ps = cnn.prepareStatement(sql);
            //使用SQL字符串创建语句句柄
            rs = ps.executeQuery();
            //执行语句获取结果集
            while (rs.next()) {
                String os = rs.getString(1);
                //获取某一类操作系统名称
                sql = "select count(*) from k_history where k_os = '" + os + "'";
                //获取某一名称操作系统的访问次数
                System.out.println(sql);
                //将SQL语句打印在日志信息中
                PreparedStatement pss = cnn.prepareStatement(sql);
                //使用SQL字符串创建语句句柄
                ResultSet rss = pss.executeQuery();
                 //执行语句获取结果集
                rss.next();
                //游标指向结果集中第一条记录
                data.setValue(os, rss.getInt(1));
                //将二元组（操作系统名字，访问次数）保存到数据集中
                DBHandle.closeResource(pss, rss, null);
                //释放在本次循环中的结果集和语句句柄
            }
        }
        catch (Exception es) {
            throw es;
            //直接将异常抛出，由外部程序处理
        }
        finally {
            DBHandle.closeResource(ps, rs, cnn);
            //释放连接句柄以及其他未释放的资源
        }
        return data;
    }

    /**
     * 获取浏览器类型统计,并保存到数据集（JFreeChart要用到）中
     * @throws Exception
     * @return DefaultPieDataset
     */
    public static DefaultPieDataset getbrowserStat() throws
        Exception {
        Connection cnn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        DefaultPieDataset data = new DefaultPieDataset();
        //数据集，用于保存操作系统类型统计数据
        try {
            cnn = DBHandle.getConn();
            //获取连接句柄
            String sql = "select distinct k_browser from k_history";
            //从历史记录表中获取操作系统类型
            ps = cnn.prepareStatement(sql);
            //使用SQL字符串创建语句句柄
            rs = ps.executeQuery();
            //执行语句获取结果集
            while (rs.next()) {
                String browser = rs.getString(1);
                //获取某一类操作系统名称
                sql = "select count(*) from k_history where k_browser = '" + browser + "'";
                //获取某一名称操作系统的访问次数
                System.out.println(sql);
                //将SQL语句打印在日志信息中
                PreparedStatement pss = cnn.prepareStatement(sql);
                //使用SQL字符串创建语句句柄
                ResultSet rss = pss.executeQuery();
                 //执行语句获取结果集
                rss.next();
                //游标指向结果集中第一条记录
                data.setValue(browser, rss.getInt(1));
                //将二元组（操作系统名字，访问次数）保存到数据集中
                DBHandle.closeResource(pss, rss, null);
                //释放在本次循环中的结果集和语句句柄
            }
        }
        catch (Exception es) {
            throw es;
            //直接将异常抛出，由外部程序处理
        }
        finally {
            DBHandle.closeResource(ps, rs, cnn);
            //释放连接句柄以及其他未释放的资源
        }
        return data;
    }

    public static DefaultPieDataset getbrowserStat2() throws
        Exception {
        Connection cnn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        DefaultPieDataset chart = new DefaultPieDataset();
        try {
            cnn = DBHandle.getConn();
            //获取连接句柄
            String sql = "select distinct k_browser from k_history";
            System.out.println(sql);
            ps = cnn.prepareStatement(sql); //创建语句句柄
            rs = ps.executeQuery();
            while (rs.next()) {
                String browser = rs.getString(1);
                sql = "select count(*) from k_history where k_browser = '" +
                    browser + "'";
                System.out.println(sql);
                PreparedStatement pss = cnn.prepareStatement(sql); //创建语句句柄
                ResultSet rss = pss.executeQuery();
                rss.next();
                chart.setValue(browser, rss.getInt(1));
                DBHandle.closeResource(pss, rss, null);
            }
        }
        catch (Exception es) {
            throw es;
        }
        finally {
            DBHandle.closeResource(ps, rs, cnn); //释放语句句柄和连接句柄
        }
        return chart;
    }

    /**
     * 查询页面访问次数
     */
    public static int select(String url) throws
        Exception {
        Connection cnn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        int count = 0;
        try {
            cnn = DBHandle.getConn();
            //获取连接句柄
            ps = cnn.prepareStatement(
                "select count(*) from k_history where k_url='"+url+"'");
            //创建语句句柄
            rs = ps.executeQuery();
            //执行查询语句，获取结果集
            rs.next();
            //游标指向第一条记录
            count = rs.getInt(1);
            //记录访问次数
        }
        catch (Exception es) {
            throw es;
            //直接将异常抛出，由外部程序处理
        }
        finally {
            DBHandle.closeResource(ps, rs, cnn);
            //释放语句句柄、连接句柄、结果集
        }
        return count;
    }
    
    /**
     * 查询访问站点次数
     */
    public static int select() throws
        Exception {
        Connection cnn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        int count = 0;
        try {
            cnn = DBHandle.getConn();
            //获取连接句柄
            ps = cnn.prepareStatement(
                "select count(*) from k_history");
            //创建语句句柄
            rs = ps.executeQuery();
            //执行查询语句，获取结果集
            rs.next();
            //游标指向第一条记录
            count = rs.getInt(1);
            //记录访问次数
        }
        catch (Exception es) {
            throw es;
            //直接将异常抛出，由外部程序处理
        }
        finally {
            DBHandle.closeResource(ps, rs, cnn);
            //释放语句句柄、连接句柄、结果集
        }
        return count;
    }

}
